﻿using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net;
using System.Windows.Forms;
using System.Xml;
using System.Xml.Linq;
using FBEntities;
using FBEntities.FBObjects;
using Microsoft.WindowsCE.Forms;
using XFControls;
using XFControls.Utils;
using XFControls.XFPanels;
using XFSenseUI;
using XFSenseUI.XFItems;
using XFSenseUI.XFItems.SenseControls;
using XFItemControls.XFPanels;

namespace XDAFacebook
{
    public sealed partial class Main : Form
    {
        private readonly string debugFileName = "\\XDAFacebookDebug.xml";
        private readonly string email;

        private SenseItemControl _saveSettings;
        private Authentication auth;
        private XDocument settings;

        public Main()
        {
            InitializeComponent();

            Text += " " + Settings.CurrentVersion;
            xfPanelContainer.SetHeader(xfPanelHeader);

            using (var splash = new SplashScreen())
            {
                splash.Show();

                while (!splash.CheckAuth)
                    Application.DoEvents();
                debugFileName = Settings.GetCurrent_Directory() + debugFileName;
                email = loadSettings();

                if (string.IsNullOrEmpty(auth.AuthKey))
                    setupLogin();
                else
                    setupMain();
            }
        }

        private void setupMain()
        {
            miHome.Enabled = true;
            miUploadPhotos.Enabled = true;
            miLogOut.Enabled = true;

            if (XFItemControlUtils.Me == null)
            {
                var me = new FBDataSource(auth.AuthKey);
                XFItemControlUtils.Me = me;
            }
            var panel = new XFPanelHomeIcon(Settings.HomeIcons);

            xfPanelContainer.SetMainPanel(panel);
            var notifications = new FBNotifications();
            notifications.Clicked += (o, e) =>
                                     {
                                         xfPanelContainer.MainPanel.SetRightPanel(XFPanelHomeIcon.GetRequestsPanel(xfPanelContainer));
                                         xfPanelContainer.MainPanel.EnableSlide();
                                     };

            xfPanelContainer.UpdateNotification = notifications;
            xfPanelContainer.UpdateNotification.StartUpdates();

            miExit.Text = Settings.LocalizationStrings.Exit;
            miHome.Text = Settings.LocalizationStrings.Home;
            miLogOut.Text = Settings.LocalizationStrings.logOut;
            miMenu.Text = Settings.LocalizationStrings.Menu;
            miSettings.Text = Settings.LocalizationStrings.settings;
            miAbout.Text = Settings.LocalizationStrings.About;
            miUploadPhotos.Text = Settings.LocalizationStrings.UploadPhotos;

            if (Settings.FirstRun == Settings.CurrentVersion) return;

            Cursor.Current = Cursors.WaitCursor;
            Application.DoEvents();

            if (File.Exists(XFControlUtils.GetCurrent_Directory() + "\\data.xfd"))
                File.Delete(XFControlUtils.GetCurrent_Directory() + "\\data.xfd");

            XFGraphics.ClearImageCache();
            string skinPath = XFControlUtils.GetCurrent_Directory() + @"\Resources\";
            if (Settings.Skin != Settings.LocalizationStrings.Default && Directory.Exists(Settings.SkinDir + "\\" + Settings.Skin))
                skinPath = Settings.SkinDir + "\\" + Settings.Skin;

            XFGraphics.DoImport(skinPath);
            Settings.FirstRun = Settings.CurrentVersion;
            Settings.SaveSettings();

            Cursor.Current = Cursors.Default;
            Application.DoEvents();

            MessageBox.Show(
                "Thank you for downloading XDAFacebook!\nFor a list of new features, check out the Forum page from the About menu.\nWhile you're there feel free to click the DONATE button!",
                "Welcome!", MessageBoxButtons.OK, MessageBoxIcon.None, MessageBoxDefaultButton.Button1);
        }

        private void setupLogin()
        {
            miHome.Enabled = false;
            miUploadPhotos.Enabled = false;
            miLogOut.Enabled = false;

            var panel = new SenseListPanel
                        {
                            PanelName = "XDA Facebook"
                        };
            xfPanelContainer.SetMainPanel(panel);

            var div = new SenseItemDivider
                      {
                          Text = Settings.LocalizationStrings.login
                      };

            var ddType = new SenseItemDropDown
                         {
                             Description = Settings.LocalizationStrings.loginType
                         };

            ddType.Options.Add(Settings.LocalizationStrings.externWebLogin);
            ddType.Options.Add(Settings.LocalizationStrings.internLogin);
            ddType.Options.Add(Settings.LocalizationStrings.internWebLogin);
            ddType.SelectionChanged += (sender, args) =>
                                       {
                                           panel.ClearItems(panel[ddType] + 1);

                                           if (args.Text == Settings.LocalizationStrings.internLogin)
                                           {
                                               var tbUser = new SenseItemTextBox
                                                            {
                                                                Description = Settings.LocalizationStrings.userName,
                                                                Text = email
                                                            };
                                               var tbPass = new SenseItemTextBox
                                                            {
                                                                Description = Settings.LocalizationStrings.password
                                                            };
                                               tbPass.TextBox.PasswordChar = '*';

                                               var login = new SenseItem
                                                           {
                                                               MainText = Settings.LocalizationStrings.clickToLogin,
                                                               MultiLine = true
                                                           };

                                               login.Click += (o, e) => { if (authenticate(tbUser.Text, tbPass.Text)) setupMain(); };

                                               panel.AddSenseItem(tbUser);
                                               panel.AddSenseItem(tbPass);

                                               _saveSettings = new SenseItemControl
                                                               {
                                                                   MainText = Settings.LocalizationStrings.saveLogin,
                                                                   Control = new SenseControlCheckbox()
                                                               };

                                               panel.AddSenseItem(_saveSettings);
                                               panel.AddSenseItem(login);
                                           }
                                           else if (args.Text == Settings.LocalizationStrings.internWebLogin)
                                           {
                                               var webBrowser = new SenseItem
                                                                {
                                                                    MainText = Settings.LocalizationStrings.clickToLaunchBrowserInternal,
                                                                    MultiLine = true
                                                                };

                                               webBrowser.Click += (o, e) =>
                                                                   {
                                                                       if (btWebLogin_Click())
                                                                           setupMain();
                                                                   };

                                               _saveSettings = new SenseItemControl
                                                               {
                                                                   MainText = Settings.LocalizationStrings.saveLogin,
                                                                   Control = new SenseControlCheckbox()
                                                               };

                                               panel.AddSenseItem(_saveSettings);
                                               panel.AddSenseItem(webBrowser);
                                           }
                                           else if (args.Text == Settings.LocalizationStrings.externWebLogin)
                                           {
                                               var exWebBrowser = new SenseItem
                                                                  {
                                                                      MainText = Settings.LocalizationStrings.clickToLaunchBrowserExternal,
                                                                      MultiLine = true
                                                                  };
                                               exWebBrowser.Click += (o, e) =>
                                                                     {
                                                                         MessageBox.Show(Settings.LocalizationStrings.browserMessage);
                                                                         Process.Start(Authentication.authURL, null);
                                                                     };

                                               var paste = new SenseItem
                                                           {
                                                               MainText = Settings.LocalizationStrings.copyUrl,
                                                               MultiLine = true
                                                           };
                                               paste.Click += (o, e) =>
                                                              {
                                                                  if (paste_Click())
                                                                      setupMain();
                                                              };

                                               panel.AddSenseItem(exWebBrowser);

                                               _saveSettings = new SenseItemControl
                                                               {
                                                                   MainText = Settings.LocalizationStrings.saveLogin,
                                                                   Control = new SenseControlCheckbox()
                                                               };

                                               panel.AddSenseItem(_saveSettings);
                                               panel.AddSenseItem(paste);
                                           }
                                       };

            panel.AddSenseItem(div);
            panel.AddSenseItem(ddType);

            ddType.Select(0);
        }

        /// <summary>
        /// Authenticates the user.  This method is ran on a background thread.
        /// </summary>
        /// <param name="val">The val.</param>
        private bool authenticate(string user, string pass)
        {
            Cursor.Current = Cursors.WaitCursor;
            Application.DoEvents();

            auth = new Authentication(user, pass);
            AuthenticationReturn res = auth.Authenticate();

            Cursor.Current = Cursors.Default;
            Application.DoEvents();

            switch (res)
            {
                case AuthenticationReturn.BadLogin:
                    MessageBox.Show(Settings.LocalizationStrings.incorrectPassword); // Or could be another error
                    break;
                case AuthenticationReturn.Success:
                    //Sucess!  Now start doing stuff
                    var me = new FBDataSource(auth.AuthKey);
                    XFItemControlUtils.Me = me;
                    saveSettings(user);
                    return true;
                case AuthenticationReturn.TimeOut:
                    MessageBox.Show(Settings.LocalizationStrings.serverTimeout); // Or could be another error
                    break;
                case AuthenticationReturn.Unknown:
                    MessageBox.Show(Settings.LocalizationStrings.unknownError); // Or could be another error
                    break;
            }
            return false;
        }

        /// <summary>
        /// Loads the app settings.
        /// </summary>
        private string loadSettings()
        {
            auth = new Authentication();
            string ret = "";
            if (File.Exists(Settings.settingsFileName))
            {
                try
                {
                    settings = XDocument.Load(Settings.settingsFileName);

                    if (settings.Root.Descendants("email").Any())
                        ret = settings.Root.Element("email").Value;
                    else
                        settings.Root.Add(new XElement("email"));

                    if (settings.Root.Descendants("auth_key").Any())
                        auth = new Authentication(settings.Root.Element("auth_key").Value.Decrypt());
                    else
                        settings.Root.Add(new XElement("auth_key"));
                }
                catch (XmlException)
                {
                    settings = new XDocument(
                        new XDeclaration("1.0", "utf-8", "yes"),
                        new XElement("settings",
                                     new XElement("email"),
                                     new XElement("auth_key")));
                }
            }
            else
                settings = new XDocument(
                    new XDeclaration("1.0", "utf-8", "yes"),
                    new XElement("settings",
                                 new XElement("email"),
                                 new XElement("auth_key")));

            return ret;
        }

        private void saveSettings(string user)
        {
            if (((SenseControlCheckbox)_saveSettings.Control).Checked)
            {
                if (auth != null && !string.IsNullOrEmpty(auth.AuthKey))
                {
                    settings.Root.Element("auth_key").SetValue(auth.AuthKey.Encrypt());

                    if (!string.IsNullOrEmpty(user))
                        settings.Root.Element("email").SetValue(user);
                    settings.Save(Settings.settingsFileName);
                }
            }
            else
            {
                settings.Root.Element("auth_key").SetValue("");
                settings.Root.Element("email").SetValue("");
                settings.Save(Settings.settingsFileName);
            }
        }

        private bool btWebLogin_Click()
        {
            bool ret = false;
            using (var authPage = new LoginWeb(Authentication.authURL, Authentication.authKeyURL, Authentication.successUrl))
            {
                authPage.ShowDialog();
                if (authPage.updated)
                {
                    auth = new Authentication(authPage.token_text);

                    var me = new FBDataSource(auth.AuthKey);
                    XFItemControlUtils.Me = me;

                    ret = true;
                    saveSettings(null);
                }
            }
            return ret;
        }

        private bool paste_Click()
        {
            IDataObject iData = Clipboard.GetDataObject();
            try
            {
                if (iData.GetDataPresent(DataFormats.Text))
                {
                    // Yes it is, so display it in a text box.
                    string exchangeUrl = Authentication.authKeyURL;
                    var accessurl = (String)iData.GetData(DataFormats.Text);
                    string accessCode = accessurl.Split('?').Last().Split('&').FirstOrDefault(i=>i.StartsWith("code"));
                    if (!string.IsNullOrEmpty(accessCode))
                        accessCode = accessCode.Substring(5);

                    exchangeUrl += accessCode;

                    WebRequest myWebRequest = WebRequest.Create(exchangeUrl);
                    using (WebResponse myWebResponse = myWebRequest.GetResponse())
                    {
                        string responseData;
                        using (var resp = myWebResponse.GetResponseStream())
                        using (var streamReader = new StreamReader(resp))
                        {
                            responseData = streamReader.ReadToEnd();
                        }

                        auth = new Authentication(responseData);
                    }
                    var me = new FBDataSource(auth.AuthKey);
                    XFItemControlUtils.Me = me;

                    saveSettings(null);
                    return true;
                }

                MessageBox.Show(Settings.LocalizationStrings.copyUrlError);
            }
            catch (Exception e)
            {
                MessageBox.Show(Settings.LocalizationStrings.copyUrlError);
            }

            return false;
        }

        private void miExit_Click(object sender, EventArgs e)
        {
            Dispose();
            Application.Exit();
        }

        private void miLogOut_Click(object sender, EventArgs e)
        {
            if (File.Exists(Settings.settingsFileName))
            {
                XDocument settingsXml = XDocument.Load(Settings.settingsFileName);

                if (settingsXml.Root.Descendants("auth_key").Any())
                    settingsXml.Root.Element("auth_key").Value = "";

                settingsXml.Save(Settings.settingsFileName);
            }
            setupLogin();
        }

        private void miUploadPhotos_Click(object sender, EventArgs e)
        {
            var uploader = new PhotoUploader();
            uploader.ShowDialog();
        }

        private void miHome_Click(object sender, EventArgs e)
        {
            XFGraphics.ClearDownloadQueue();
            XFPanelContainer mp = xfPanelContainer;
            if (mp.MainPanel is XFPanelHomeIcon) return;

            if (mp.MainPanel.Height < Screen.PrimaryScreen.WorkingArea.Height)
                mp.MainPanel.Height = Screen.PrimaryScreen.WorkingArea.Height;

            var home = new XFPanelHomeIcon(Settings.HomeIcons);

            mp.MainPanel.SetLeftPanel(home);
            mp.MainPanel.EnableSlide();
        }

        private void miAbout_Click(object sender, EventArgs e)
        {
            var About = new About();
            About.ShowDialog();
        }

        private void miSettings_Click(object sender, EventArgs e)
        {
            var menu = new SettingsMenu();
            menu.ShowDialog();
        }

        private void menuItem1_Click(object sender, EventArgs e)
        {
            SystemSettings.ScreenOrientation = SystemSettings.ScreenOrientation == ScreenOrientation.Angle0
                                                   ? ScreenOrientation.Angle90
                                                   : ScreenOrientation.Angle0;
        }

        private void miUpdateStatus_Click(object sender, EventArgs e)
        {
            XFPanelContainer mp = xfPanelContainer;

            var user = XFItemControlUtils.Me.Me;
            var input = new XFPanelTextInput();

            input.Submitted += (o, ex) =>
            {
                Cursor.Current = Cursors.WaitCursor;
                Application.DoEvents();

                var wrap = user.UpdateStatus(ex.Text);
                string res = wrap.Post();
                Cursor.Current = Cursors.Default;
            };

            input.PanelName = "Update Status";

            mp.MainPanel.SetRightPanel(input);
            mp.MainPanel.EnableSlide();

        }
    }
}